﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace melodyMe
{
    public partial class PlaylistDJ : Form
    {
        private string playlistDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\melodyMe\\Playlists\\");

        List<string[]> tracksInPlaylist = new List<string[]>();
        string currentPlaylistName;

        int lastSelectedIndexLast = 0;
        int lastSelectedIndexNext = 0;

        Encryption encClass;

        public PlaylistDJ()
        {
            InitializeComponent();
            Get_Playlists();

            //Setup Exporting Encryption Class.
            encClass = new Encryption();
        }

        #region Playlist Fetching & Editing Code (CREATE, LOAD, GET, DELETE, UPDATE)
        /// <summary>
        /// Gets an array of every playlist from the Playlist folder and stores them in the Left Listbox (listPlaylists).
        /// </summary>
        private void Get_Playlists()
        {
            string playlistDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\melodyMe\\Playlists\\");
            string[] playlists;

            //Clear the list of old data.
            listPlaylists.Items.Clear();
            tracksInPlaylist.Clear();

            if (!Directory.Exists(playlistDirectory))
            { Directory.CreateDirectory(playlistDirectory); }

            playlists = Directory.GetFiles(playlistDirectory);

            foreach (string file in playlists)
            {
                FileInfo fi = new FileInfo(file);
                listPlaylists.Items.Add(fi.Name);
            }
        }

        /// <summary>
        /// Loads a selected playlist from the left Listbox of playlists on file.
        /// </summary>
        private void LoadSelectedPlaylist()
        {
            //If we've already caught the playlist name when they selected the playlist, then it's okay.
            //We can use that if it's nulled by a track-in-playlist selection.
            if (listPlaylists.SelectedItem != null)
            { currentPlaylistName = listPlaylists.SelectedItem.ToString(); }

            string mmPL = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\melodyMe\\Playlists\\" + currentPlaylistName);
            bool PListExists = File.Exists(mmPL);

            if (PListExists)
            {
                //Remove old songs from the arrays/lists.
                listTracksInPlaylist.Items.Clear();

                try
                {
                    StreamReader streamR = new StreamReader(mmPL);

                    string tempString = streamR.ReadLine();
                    while (tempString != null)
                    {
                        string[] readTrack = tempString.Split('|');

                        listTracksInPlaylist.Items.Add(readTrack[0]);
                        tracksInPlaylist.Add(readTrack);
                        tempString = streamR.ReadLine();
                    }
                    streamR.Close();
                }
                catch (System.Exception ex) { MessageBox.Show(ex.Message, "melodyMe"); }
            }
        }
        /// <summary>
        /// Removes the selected playlist from the file and program.
        /// </summary>
        private void DeleteSelectedPlaylist()
        {
            try
            {

                string playlistToDelete = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
                    + "\\melodyMe\\Playlists\\" + currentPlaylistName);

                File.Delete(playlistToDelete);
                
                //Clear items and refresh plist box.
                listTracksInPlaylist.Items.Clear();
                Get_Playlists();
            }
            catch (System.Exception ex) { MessageBox.Show("Could not delete playlist:\n" + ex.Message); }
        }

        /// <summary>
        /// Creates a new playlist file based on a name input by the user.
        /// If the file already exists, it will be deleted for data safety.
        /// </summary>
        private void CreateNewPlaylist()
        {
            try
            {
                string plistDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\melodyMe\\Playlists\\");
                SaveAsForm createPlaylistForm = new SaveAsForm("Create New Playlist");
                createPlaylistForm.ShowDialog();

                string newPLFilename = plistDir + createPlaylistForm.FileName;

                if (File.Exists(newPLFilename))
                { File.Delete(newPLFilename); }

                else if (createPlaylistForm.FileName != null)
                { File.Create(newPLFilename).Close(); }
            }
            catch (System.Exception ex) { MessageBox.Show("Could not create playlist:\n" + ex.Message); }
        }

        /// <summary>
        /// Updates the file on disk that holds the Playlist. Used to prevent data loss.
        /// </summary>
        /// <param name="updateThisFile"></param>
        private void UpdatePlaylist(string updateThisFile)
        {
            string mmDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\melodyMe\\Playlists\\");
            bool mmDirExists = Directory.Exists(mmDir);

            if (!mmDirExists)
            { Directory.CreateDirectory(mmDir); }

            //Remove the current file to stop non-overwriting. Erm... It makes sense in my head...
            if (File.Exists(mmDir + updateThisFile))
            { File.Delete(mmDir + updateThisFile); }

            StreamWriter streamW = new StreamWriter(mmDir + updateThisFile);
            try
            {
                foreach (string[] sa in tracksInPlaylist)
                {
                    //Write both parts to a line with the delimiter char.
                    streamW.WriteLine(sa[0] + " | " + sa[1] + " | " + sa[2]);
                }
            }
            catch { MessageBox.Show("Could not save playlist."); }
            streamW.Close();

            //And update the list of playlists!
            Get_Playlists();
        }
        #endregion

        #region Button Mashing Code
        private void btnDeletePlaylist_Click(object sender, EventArgs e)
        {
            if (listPlaylists.SelectedIndex >= 0)
            {
                DeleteSelectedPlaylist();
                Get_Playlists(); //Refresh playlists shown to user.
            }
        }

        private void btnCreateNewPlaylist_Click(object sender, EventArgs e)
        {
            CreateNewPlaylist();
            Get_Playlists(); //Refresh Playlist Listbox...
        }

        private void btnRemoveTrackFromPlaylist_Click(object sender, EventArgs e)
        {
            int currentIndex = listTracksInPlaylist.SelectedIndex;
            if (currentIndex >= 0)
            {
                try
                {
                    //Remove from the Listbox on the form.
                    listTracksInPlaylist.Items.RemoveAt(currentIndex);
                    tracksInPlaylist.RemoveAt(currentIndex);

                    //Make a call to save updated playlist to file.
                    UpdatePlaylist(listPlaylists.SelectedItem.ToString());
                }
                catch (System.Exception) { }
            }
        }

        private void btnRenameTrack_Click(object sender, EventArgs e)
        {
            //What is the selected track we're renaming?
            int thisSelectedIndex = listTracksInPlaylist.SelectedIndex;

            if (thisSelectedIndex <= tracksInPlaylist.Count || thisSelectedIndex >= 0)
            {
                try
                {
                    //Pop the saveAs Form to get input on the new name for this track.
                    SaveAsForm newTrackNameForm = new SaveAsForm("Choose New Track Name");
                    newTrackNameForm.ShowDialog();
                    string newName = newTrackNameForm.FileName;

                    //Issue the rename, add back into, and save the playlist.
                    string[] currentTrack = tracksInPlaylist[thisSelectedIndex];
                    tracksInPlaylist.RemoveAt(thisSelectedIndex);
                    currentTrack[0] = newName;
                    tracksInPlaylist.Insert(thisSelectedIndex, currentTrack);

                    UpdatePlaylist(listPlaylists.SelectedItem.ToString());

                    //Refresh the list of Playlists.
                    Get_Playlists();
                }
                catch (System.Exception) { }
            }
        }

        private void btnMoveTrackUp_Click(object sender, EventArgs e)
        {
            int thisSelectedIndex = 0;

            //If we've just bumped one down, and the current Index is -1.
            //Assuming the lastSI wasn't -1/null, we can use that. :)
            if ((listTracksInPlaylist.SelectedIndex == -1) && (lastSelectedIndexNext <= listTracksInPlaylist.Items.Count))
            { thisSelectedIndex = lastSelectedIndexNext; }
            else
            { thisSelectedIndex = listTracksInPlaylist.SelectedIndex; }

            int nextIndex = thisSelectedIndex--;

            if (nextIndex <= listTracksInPlaylist.Items.Count)
            {
                try
                {
                    //Pop the saveAs Form to get input on the new name for this track.
                    string[] currentTrack = tracksInPlaylist[thisSelectedIndex];
                    tracksInPlaylist.RemoveAt(thisSelectedIndex);
                    tracksInPlaylist.Insert(nextIndex, currentTrack);

                    UpdatePlaylist(currentPlaylistName);
                    //Update the lastSI for multiple drops down.
                    lastSelectedIndexNext = thisSelectedIndex;
                    //Refresh the list of Playlists.
                    LoadSelectedPlaylist();
                }
                catch (System.Exception) { }
            }
        }

        private void btnMoveTrackDown_Click(object sender, EventArgs e)
        {
            int thisSelectedIndex = 0;

            //If we've just bumped one down, and the current Index is -1.
            //Assuming the lastSI wasn't -1/null, we can use that. :)
            if ((listTracksInPlaylist.SelectedIndex == -1) && (lastSelectedIndexLast >= 0))
            { thisSelectedIndex = lastSelectedIndexLast; }
            else
            { thisSelectedIndex = listTracksInPlaylist.SelectedIndex; }

            int nextIndex = thisSelectedIndex++;

            if (nextIndex <= listTracksInPlaylist.Items.Count)
            {
                try
                {
                    //Pop the saveAs Form to get input on the new name for this track.
                    string[] currentTrack = tracksInPlaylist[thisSelectedIndex];
                    tracksInPlaylist.RemoveAt(thisSelectedIndex);
                    tracksInPlaylist.Insert(nextIndex, currentTrack);

                    UpdatePlaylist(currentPlaylistName);
                    //Update the lastSI for multiple drops down.
                    lastSelectedIndexLast = thisSelectedIndex;
                    //Refresh the list of Playlists.
                    LoadSelectedPlaylist();
                }
                catch (System.Exception) { }
            }
        }
        #endregion

        private void listPlaylists_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Remove any old tracks out of the List.
            tracksInPlaylist.Clear();
            LoadSelectedPlaylist();
        }

        /// <summary>
        /// Handles exporting a playlist - Get Data / Encrypt / Save To Location
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExport_Click(object sender, EventArgs e)
        {
            if (listPlaylists.SelectedIndex != -1)
            {
                try
                {
                    SaveFileDialog exportPathDialog = new SaveFileDialog();
                    exportPathDialog.Title = "Save to Path";
                    exportPathDialog.AddExtension = true;
                    exportPathDialog.DefaultExt = ".mmpl";
                    exportPathDialog.Filter = "melodyMe Playlist (*.mmpl) | *.mmpl";
                    exportPathDialog.FileName = listPlaylists.SelectedItem.ToString();

                    if (exportPathDialog.ShowDialog() == DialogResult.OK)
                    {
                        string exportPath = exportPathDialog.FileName;
                        StreamWriter sw = new StreamWriter(exportPath);
                        StreamReader sr = new StreamReader(playlistDir+currentPlaylistName);
                        List<string> trackListing = new List<string>();

                        //Read in all the tracks as strings, than use tracksinPlaylist (that's string[])
                        string trackRead = sr.ReadLine();
                        while (trackRead != null)
                        {
                            trackListing.Add(trackRead);
                            trackRead = sr.ReadLine();
                        }
                        sr.Close();

                        foreach (string track in trackListing)
                        { sw.WriteLine(encClass.Encrypt(track)); }

                        sw.Close();
                        MessageBox.Show("Successfully exported: " + currentPlaylistName);
                    }
                }
                catch (System.Exception ex) { MessageBox.Show("Could not export playlist:\n" + ex.Message); }
            }
        }

        /// <summary>
        /// Handles importing a playlist - Open / Decrypt / Put in %appdata%
        /// </summary>s
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnImport_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog importPathDialog = new OpenFileDialog();
                importPathDialog.Filter = "melodyMe Playlist (*.mmpl) | *.mmpl";
                importPathDialog.Title = "Import Path";

                if (importPathDialog.ShowDialog() == DialogResult.OK)
                {
                    //Get filename without .iceList
                    string importFileName = importPathDialog.SafeFileName.Substring(0, importPathDialog.SafeFileName.Length - 4);
                    StreamReader sr = new StreamReader(importPathDialog.FileName);
                    StreamWriter sw = new StreamWriter(playlistDir + importFileName);

                    string encryptedRead = sr.ReadLine();
                    while (encryptedRead != null)
                    {
                        string decData = encClass.Decrypt(encryptedRead);
                        sw.WriteLine(decData);
                        sw.Flush();
                        encryptedRead = sr.ReadLine();
                    }

                    sr.Close();
                    sw.Close();

                    //Refresh playlist box to show new playlist!
                    Get_Playlists();
                }

            }
            catch (System.Exception ex) { MessageBox.Show("Could not import playlist:\n" + ex.Message); }
        }
    }
}